package com.wiscamp.ninechapters.panels.domain.services;

import com.wiscamp.ninechapters.panels.domain.repositories.PanelsErrorCodes;
import com.wiscamp.ninechapters.panels.domain.entities.Application;
import com.wiscamp.ninechapters.panels.domain.events.ApplicationCreatedEvent;
import com.wiscamp.ninechapters.panels.domain.repositories.ApplicationRepository;
import cube.common.cache.CacheManagerNames;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.domain.BaseDomainService;
import cube.ddd.exception.ExceptionUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class ApplicationService extends BaseDomainService {
    private final ApplicationRepository applicationRepository;

    public ApplicationService(ApplicationRepository applicationRepository) {
        this.applicationRepository = applicationRepository;
    }

    private final String cacheName = "applications";

    @HandleServiceException
    @Cacheable(value = cacheName, key = "#appId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Application getApplication(long appId) {
        var app = applicationRepository.getApplication(appId);
        if (Objects.isNull(app)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.APPLICATION_NOT_FOUND, appId);
        }

        // 国际化能力测试
        /*var hello1 = applicationContext.getMessage("hello", null, Locale.US);
        var hello2 = applicationContext.getMessage("hello", null, Locale.CHINA);
        var hello3 = messageUtils.get("hello");
        logger.warn("hello1 : {}", hello1);
        logger.warn("hello2 : {}", hello2);
        logger.warn("hello3 : {}", hello3);*/

        return app;
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#app.applicationId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Application createApplication(Application app, long operatorId) {
        var existedApp = applicationRepository.getApplicationByCode(app.getApplicationCode());
        if (Objects.nonNull(existedApp)) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.APPLICATION_CODE_EXISTED, app);
        }

        app.initSecretKey();
        app.createBy(operatorId);
        var createdApp = applicationRepository.saveApplication(app);
        applicationContext.publishEvent(new ApplicationCreatedEvent(this, createdApp.getApplicationId()));
        return createdApp;
    }

    @HandleServiceException
    @CachePut(value = cacheName, key = "#app.applicationId", cacheManager = CacheManagerNames.SIXTY_MINUTES_CACHE)
    public Application updateApplication(Application app, long operatorId) {
        var existedApp = getApplication(app.getApplicationId());

        existedApp = applicationRepository.getApplicationByCode(app.getApplicationCode());
        if (Objects.nonNull(existedApp) && existedApp.getApplicationId() != app.getApplicationId()) {
            ExceptionUtils.throwServiceException(PanelsErrorCodes.APPLICATION_CODE_EXISTED, app);
        }
        app.updateBy(operatorId);
        return applicationRepository.saveApplication(app);
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#appId")
    public boolean enableApplication(long appId, long operatorId) {
        var app = getApplication(appId);
        if (Objects.isNull(app)) return false;

        // 记录操作日志
        app.enable();
        app.updateBy(operatorId);
        applicationRepository.saveApplication(app);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#appId")
    public boolean disableApplication(long appId, long operatorId) {
        var app = getApplication(appId);
        if (Objects.isNull(app)) return false;
        // 记录操作日志
        app.disable();
        app.updateBy(operatorId);
        applicationRepository.saveApplication(app);
        return true;
    }

    @HandleServiceException
    @CacheEvict(value = cacheName, key = "#appId")
    public boolean deleteApplication(long appId, long operatorId) {
        var app = getApplication(appId);
        if (Objects.isNull(app)) return false;
        // 记录操作日志
        app.delete();
        app.updateBy(operatorId);
        applicationRepository.saveApplication(app);
        return true;
    }
}
